#include "PerlinNoise.hlsl"

#define blocksize 512

struct Beam_Vertex
{
	float3 vCP;
	float3 vSP;
};

cbuffer CB //: register( b0 )
{	
	matrix	g_mWorld;		//: packoffset( c1 );
	float3 	g_vEyePos;		//: packoffset( c0 );
	float 	g_fWidth;		//: packoffset( c0.w );

	float   g_fSpeed;
	float   g_fScale;		
	float   g_fElapsedTime;
	float   padding;
};

StructuredBuffer<float3> ControlPositions : register(t0);
RWStructuredBuffer<float3> PerlinSeeds: register(u0);
RWStructuredBuffer<Beam_Vertex> BeamVertexBuffer : register(u1);

groupshared float3 sharedCP[256];
groupshared float3 sharedVB[512];

float3 noise3(float3 input)
{
	float3 output;
	output.x = PerlinNoise(input.x);
	output.y = PerlinNoise(input.y);
	output.z = PerlinNoise(input.z);
	return output;
}

[numthreads(blocksize, 1, 1)]
void CSMain( uint3 DTid : SV_DispatchThreadID )
{
	int VBid = DTid.x * 2;

	float fAdvance = g_fSpeed * g_fElapsedTime;
    #ifdef FACE_TO_CAMERA	
   		// load ControlPoints
		float3 vPos = ControlPositions[DTid.x] + g_fScale * noise3(PerlinSeeds[DTid.x]);
		sharedCP[DTid.x] = mul( float4(vPos,1), g_mWorld ).xyz;
	 	PerlinSeeds[DTid.x] += float3( fAdvance, fAdvance, fAdvance ); 		
		GroupMemoryBarrierWithGroupSync();	
			
		//
		float3 vEyeDir = g_vEyePos - sharedCP[DTid.x];
		float3 vFaceNormal = sharedCP[DTid.x-1] - sharedCP[DTid.x+1];
		float3 vDir = normalize(cross(vEyeDir, vFaceNormal));

		// calc sharedVB
		sharedVB[VBid] = sharedCP[DTid.x] + vDir * g_fWidth;
		sharedVB[VBid+1] = sharedCP[DTid.x] - vDir * g_fWidth; 			
    #else
   		// load ControlPoints
		float3 vPos = ControlPositions[DTid.x] + g_fScale * noise3(PerlinSeeds[DTid.x]);
		sharedCP[DTid.x] = mul( float4(vPos,1), g_mWorld ).xyz;
	 	PerlinSeeds[DTid.x] += float3( fAdvance, fAdvance, fAdvance ); 	
		GroupMemoryBarrierWithGroupSync();	
			
		//
		float3 vDir = normalize( noise3(PerlinSeeds[DTid.x] * g_fScale) );

		// calc sharedVB
		sharedVB[VBid] = sharedCP[DTid.x] + vDir * g_fWidth;
		sharedVB[VBid+1] = sharedCP[DTid.x] - vDir * g_fWidth; 	
		/*
		float fWidth = g_fWidth * 3.0f;
		float3 vPos = mul( float4(ControlPositions[DTid.x],1), g_mWorld ).xyz;
		float3 seed = PerlinSeeds[DTid.x];
		sharedVB[VBid] = vPos + fWidth * noise3(seed);
		seed += float3(123.0f,123.0f,123.f);
		sharedVB[VBid+1] = vPos + fWidth * noise3(seed);
		PerlinSeeds[DTid.x] += float3( 0.035, 0.035, 0.035 );
		//*/
	#endif

	GroupMemoryBarrierWithGroupSync();
	// Cacl SP
	if (DTid.x % 2 == 0)
	{
		BeamVertexBuffer[VBid].vSP = lerp(sharedVB[VBid-2],sharedVB[VBid],0.5);
		BeamVertexBuffer[VBid+1].vSP = lerp(sharedVB[VBid-1],sharedVB[VBid+1],0.5);
	}
	else
	{
		BeamVertexBuffer[VBid].vSP = lerp(sharedVB[VBid+2],sharedVB[VBid],0.5);
		BeamVertexBuffer[VBid+1].vSP = lerp(sharedVB[VBid+3],sharedVB[VBid+1],0.5);		
	}

	GroupMemoryBarrierWithGroupSync();

	BeamVertexBuffer[VBid].vCP = sharedVB[VBid];
	BeamVertexBuffer[VBid+1].vCP = sharedVB[VBid+1];
}

/*

*/
